package distributedbank.requests;

import java.io.IOException;
import java.io.Serializable;

import distributedbank.responses.*;
import distributedbank.server.Account;
import distributedbank.server.BankBranch;
import distributedbank.Wrapper;

/**
 * A request to transfer a certain amount of cash from an account in the current
 * bank branch to an account at a different bank branch.
 */

public class TransferRequest extends GUIRequest
{
    private static final long serialVersionUID = -7306358893295715647L;

    private int destBranchId;

    private int destAccountId;

    private int amount; // amount to transfer in cents

    /**
     * Note: the transactionId must be globally unique!
     */
    public TransferRequest( int branchId, int accountId, int transactionId,
            int originatingClientId, int destBranchId, int destAccountId,
            int amount ) {
        super( branchId, accountId, transactionId, originatingClientId );
        this.destBranchId = destBranchId;
        this.destAccountId = destAccountId;
        this.amount = amount;
    }

    public void runRequest( BankBranch bankBranch, Wrapper wrapper )
            throws IOException {
        if( this.destBranchId == this.branchId ) {
            // don't use the network for internal transfers
            if( this.accountId == this.destAccountId ) {
                // don't do a transfer if account and dest account are the
                // same
                System.out.println( "Transfer of money between same account: "
                        + this.accountId + " at branch " + this.branchId );
                Account acc = bankBranch.getAccount( this.accountId );
                int balance = acc.query( this.transactionId );
                Serializable message = new BalanceResponse( balance );
                wrapper.sendMessage( message, this.branchId,
                        this.originatingClientId );
            } else {
                // transfer between accounts at the same branch
                System.out.println( "Transfering " + this.amount + " between "
                        + this.accountId + " and " + this.destAccountId
                        + " at branch " + this.branchId );
                Account acc = bankBranch.getAccount( this.accountId );
                Account acc2 = bankBranch.getAccount( this.destAccountId );
                int balance = acc.deposit( -this.amount, this.transactionId );
                acc2.deposit( this.amount, this.transactionId );
                Serializable message = new BalanceResponse( balance );
                wrapper.sendMessage( message, this.branchId,
                        this.originatingClientId );
            }
        } else {
            // use the network to transfer money
            System.out.println( "Transfering " + this.amount + " from account "
                    + this.accountId + " at branch " + this.branchId );
            Account acc = bankBranch.getAccount( this.accountId );
            Serializable depositMessage = new TransferDepositRequest(
                    this.branchId, this.destBranchId, this.accountId,
                    this.destAccountId, this.transactionId, this.amount );
            if( !wrapper.sendMessage( depositMessage, this.branchId,
                    this.destBranchId ) ) {
                Serializable message = new ConnErrorResponse();
                wrapper.sendMessage( message, this.branchId,
                        this.originatingClientId );
                return;
            }
            int balance = acc.deposit( -this.amount, this.transactionId );
            Serializable message = new BalanceResponse( balance );
            wrapper.sendMessage( message, this.branchId,
                    this.originatingClientId );
        }
    }
}